package com.hm.hall.user.service;

import com.hm.hall.commons.constans.ErrorCode;
import com.hm.hall.commons.constans.GameConstans;
import com.hm.hall.commons.constans.RedisKeysDefine;
import com.hm.hall.commons.constans.RedisSecondConstants;
import com.hm.hall.commons.constans.jenum.LangEnum;
import com.hm.hall.commons.dao.ChangeNameLogMapper;
import com.hm.hall.commons.dao.MobileSessionMapper;
import com.hm.hall.commons.dao.UserMapper;
import com.hm.hall.commons.domain.ChangeNameLog;
import com.hm.hall.commons.domain.MobileSession;
import com.hm.hall.commons.domain.User;
import com.hm.hall.commons.domain.UserExample;
import com.hm.hall.commons.domain.resp.BaseResponse;
import com.hm.hall.commons.service.IMailService;
import com.hm.hall.commons.service.RedisCacheService;
import com.hm.hall.commons.util.*;
import com.hm.hall.user.UserConstants;
import com.hm.hall.user.controller.po.SimpUserPO;
import com.hm.hall.user.controller.resp.VeryfiySessionTokenResp;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 用戶服務
 *
 * @author Administrator
 */
@Service
public class UserService {
    static Logger log = Logger.getLogger(UserService.class);

    @Autowired
    private MobileSessionMapper mobileSessionMapper;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IMailService mailSenderService;
    @Autowired
    private ChangeNameLogMapper changeNameLogMapper;

    /**
     * 获得状态OK 的用户
     */
    public User getUserByChanelAndUserNameByAllStatus(String userName, String unionid) {
        //查询用户优先返回unionid查询到的用户
        UserExample example = new UserExample();
        example.or().andUnionidEqualTo(unionid);
        List<User> users = userMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(users)) {
            return users.get(0);
        }
        example = new UserExample();
        example.or().andUsernameEqualTo(userName);
        users = userMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(users)) {
            return users.get(0);
        }

        return null;
    }

    /**
     * 获得状态OK 的用户
     */
    public User getUserByEmailByAllStatus(String email) {
        UserExample example = new UserExample();
        example.or().andEmailEqualTo(email);
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(users)) {
            return null;
        }
        return users.get(0);
    }

    /**
     * 获得状态OK 的用户
     */
    public User getUserByChanelAndUserName(String userName) {
        UserExample example = new UserExample();
        example.or().andUsernameEqualTo(userName);
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(users)) {
            return null;
        }
        return isUserStateOK(users.get(0)) ? users.get(0) : null;
    }

    /**
     * 获得状态OK 的用户DO
     */
    public User getUserDOByUserId(long userId) {
        User user = userMapper.selectByPrimaryKey(userId);
        return isUserStateOK(user) ? user : null;
    }

    public User getUserDOByUserName(String userName) {
        UserExample example = new UserExample();
        example.or().andUsernameEqualTo(userName);
        List<User> userList = userMapper.selectByExample(example);
        User user = userList.size() > 0 ? userList.get(0) : null;
        return isUserStateOK(user) ? user : null;
    }

    /**
     * 获得状态OK 的简单的用户PO
     */
    public SimpUserPO getSimpUserPOByUserId(long userId) {
        User user = getUserDOByUserId(userId);
        return convertSimpUserPOByUser(user);
    }

    /**
     * 获得状态OK 的简单的用户PO
     */
    public SimpUserPO convertSimpUserPOByUser(User user) {
        SimpUserPO simpUser = null;
        if (user != null) {
            simpUser = new SimpUserPO();
            BeanUtils.copyProperties(user, simpUser);
        }
        return simpUser;
    }

    /**
     * 验证sessiontoken的时效及有效性; 1.取用户最新一次token记录 2.比对token
     */
    public VeryfiySessionTokenResp veryfiySessionToken(long userId, String sessionToken) {
        MobileSession mobileSessionCache = null;
        // 开发环境 特殊验证
        if (!ActionUtils.isIdcEnv() && "test1402".equals(sessionToken)) {
            return new VeryfiySessionTokenResp();
        }
        String sessionkey = RedisKeysDefine.SESSIONTOKEN.replace("${userId}", "" + userId);
        String string = redisCacheService.get(sessionkey);
        if (string != null) {
            mobileSessionCache = JsonUtils.parseObject(string, MobileSession.class);
        }
        if (mobileSessionCache == null) {
            MobileSession session = mobileSessionMapper.selectByPrimaryKey(userId);
            if (session == null) {
                return new VeryfiySessionTokenResp(ErrorCode.user_invalid_session);
            } else {
                mobileSessionCache = session;
            }
        }

        if (mobileSessionCache.getFailureTime().after(new Date())
                && mobileSessionCache.getToken().equals(sessionToken)) {
            // cache set
            redisCacheService.setex(sessionkey, GameConstans.SESSIONTOKEN_EXP,
                    JsonUtils.toJSONString(mobileSessionCache));
            return new VeryfiySessionTokenResp();
        } else if (mobileSessionCache.getFailureTime().before(new Date())) {
            // token 过期
            log.error("veryfiySessionToken失败! token已过期 userId=" + userId + " session=" + sessionToken + " expect="
                    + mobileSessionCache.getToken());
            return new VeryfiySessionTokenResp(ErrorCode.user_invalid_session);
        }
        log.error("veryfiySessionToken失败! token 错误 userId=" + userId + " session=" + sessionToken + " expect="
                + mobileSessionCache.getToken());
        return new VeryfiySessionTokenResp(ErrorCode.user_invalid_session_token_failure);
    }

    public void userLogOut(long userId) {
        MobileSession mobileSessionCache = null;
        String sessionkey = RedisKeysDefine.SESSIONTOKEN.replace("${userId}", "" + userId);
        String string = redisCacheService.get(sessionkey);
        if (string != null) {
            mobileSessionCache = JsonUtils.parseObject(string, MobileSession.class);
        }
        if (mobileSessionCache == null) {
            MobileSession session = mobileSessionMapper.selectByPrimaryKey(userId);
            if (session == null) {
                return;
            } else {
                mobileSessionCache = session;
            }
        }
        mobileSessionCache.setFailureTime(new Date());
        redisCacheService.setex(sessionkey, GameConstans.SESSIONTOKEN_EXP, JsonUtils.toJSONString(mobileSessionCache));
        mobileSessionMapper.updateByPrimaryKeySelective(mobileSessionCache);

    }

    /**
     * 验证ip是否被封
     */
    public boolean veryfiyLastLoginIp(String ip) {
        return false;
    }

    /**
     * 判断用户是否正常 可用
     *
     * @param user 推广员
     * @return 账户正常返回true; 异常返回false
     */
    public boolean isUserStateOK(User user) {
        return user != null && (user.getActiveState() == GameConstans.USER_STATE_OK);
    }

    // 修改用户信息
    public BaseResponse updateUserInfo(Long userId, String avatar, String nickname, Integer sex) {
        User user = userMapper.selectByPrimaryKey(userId);
        if (null == user || StringUtils.isBlank(user.getGameChannel())) {
            return new BaseResponse(ErrorCode.user_invalid_session);
        }
        // 只有注册用户或者是游客才能修改头像和昵称
        if (!user.getGameChannel().equals(UserConstants.GAME_CHANNEL_VI)
                && !user.getGameChannel().equals(UserConstants.GAME_CHANNEL_EMAIL_AND) && !user.getGameChannel().equals(UserConstants.GAME_CHANNEL_EMAIL_IOS)) {
            return new BaseResponse(ErrorCode.channel_can_not_update_user_info);
        }
        String oldName = "";
        if (!StringUtils.isBlank(nickname) && !nickname.equals(user.getNickname())) {
            // 七天内最多修改一次头像
            if (redisCacheService.isCD(RedisKeysDefine.USER_UPDATE_USER_INFO + userId, DateUtils.A_WEEK_SEC)) {
                return new BaseResponse(ErrorCode.update_user_info_cd);
            }
            oldName = user.getNickname();
            user.setNickname(nickname);
        }
        if (!StringUtils.isBlank(avatar)) {
            user.setAvatar(avatar);
            if (avatar.equals("undefined")) {
                avatar = GameConstans.DEFAULT_AVATAR;
            }
        }
        user.setSex(sex);
        userMapper.updateByPrimaryKeySelective(user);
        //改过名
        if (!"".equals(oldName)) {
            afterChangeName(userId, oldName, user.getNickname());
        }
        return new BaseResponse();
    }

    /**
     * 改名之后 发送消息 添加记录
     *
     * @param userId
     * @param oldName
     * @param newName
     * @date 2019年5月5日 下午6:30:23
     * @version 2.5.8
     */
    public void afterChangeName(long userId, String oldName, String newName) {

        //添加管理员可见消息
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("oldName", oldName);
        params.put("userName", newName);
        /*List<ClubUser> clubList = clubUserService.getClubByUserId(userId);
		for(ClubUser clubUser : clubList){
			Long clubId = clubUser.getClubId();
			Message message = messageService.addMessage(clubId, userId, null, GameConstans.MESSAGE_CLASSIFY_CLUB, MsgTemplateEnum.T_NAME.key,
					MsgTemplateEnum.C_ClUB_DISMISS.key,JSON.toJSONString(params),new Date(), GameConstans.MESSAGE_SHOW_RANGE_ADM,null,null);
			//更新消息入口
			messageService.updateAdminDoorByClubId(clubId,MsgTemplateEnum.C_ClUB_DISMISS.key,JSON.toJSONString(params),message.getSendTime(),1);
			//发送动态消息
			notifyMessageService.sendActiveMessageToManager(clubId, clubId, GameConstans.MESSAGE_CLASSIFY_CLUB, MsgTemplateEnum.C_CHANGE_NAME_CONTENT.key, params,false,true,true,0L);
		}*/
        //添加改名记录
        ChangeNameLog record = new ChangeNameLog();
        record.setCreateTime(new Date());
        record.setUserId(userId);
        record.setNickName(newName);
        changeNameLogMapper.insertSelective(record);
    }

    public BaseResponse updatePassword(String email, String password, String passwordRe, String code) {
        User user = getUserByEmailByAllStatus(email);
        if (null == user) {
            return new BaseResponse(ErrorCode.user_not_exist);
        }
        if (!checkVerificationCode(email, code).ok()) {
            return new BaseResponse(ErrorCode.not_match_code);
        }
        if (!password.equals(passwordRe)) {
            return new BaseResponse(ErrorCode.not_equel_password);
        }
        user.setPassword(getMD5Password(passwordRe));
        userMapper.updateByPrimaryKeySelective(user);
        return new BaseResponse();
    }

    public BaseResponse sendVerificationCode(String email, String platform) {
        User user = getUserByEmailByAllStatus(email);
        if (null == user) {
            return new BaseResponse(ErrorCode.user_not_exist);
        }
        String key = RedisKeysDefine.USER_FIND_PASSWORD_SEND_CODE_CD + email;
        if (redisCacheService.isCD(key, RedisSecondConstants.MINUTE_SECOND)) {
            return new BaseResponse(ErrorCode.send_code_frequently);
        }
        String key2 = RedisKeysDefine.USER_FIND_PASSWORD_CODE + email;
        String code = redisCacheService.get(key2);
        if (null == code || StringUtils.isBlank(code)) {
            code = RandomUtil.randomFourFiguresDigits();
            redisCacheService.setex(key2, RedisSecondConstants.HALFHOUR_SECOND, code);
        }
        String idenString = "hall";
        if ("appStore".equals(platform)) {
            idenString = "52Poker";
        }
        mailSenderService.sendSimpleMail(email, "Retrieve your password Verification code:" + code + "【" + idenString + "】",
                "We just received your request to retrieve your password. The verification code is valid for 30 minutes. If it is not your operation, ignore this email.");
        return new BaseResponse();
    }

    public BaseResponse checkVerificationCode(String email, String code) {
        String redisCode = redisCacheService.get(RedisKeysDefine.USER_FIND_PASSWORD_CODE + email);
        if (null == redisCode || StringUtils.isBlank(code) || !redisCode.equals(code)) {
            return new BaseResponse(ErrorCode.not_match_code);
        }
        return new BaseResponse();
    }

    public BaseResponse modifyPassWord(long userId, String passold, String passnew) {
        User user = getUserDOByUserId(userId);
        if (null == user) {
            return new BaseResponse(ErrorCode.user_not_exist);
        }
        if (!user.getPassword().equals(getMD5Password(passold))) {
            return new BaseResponse(ErrorCode.data_repeat_dispose);
        }
        user.setPassword(getMD5Password(passnew));
        userMapper.updateByPrimaryKeySelective(user);
        return new BaseResponse();
    }

    // 将密码转换为md类型
    public String getMD5Password(String password) {
        return Md5Salt.toMD5(Md5Salt.toMD5(password + UserConstants.PASSWORD_KEY_1) + UserConstants.PASSWORD_KEY_2);
    }

    /**
     * 更换语言
     *
     * @param userId
     * @param lang
     * @return
     */
    public BaseResponse updateUserLang(Long userId, String lang) {
        User user = userMapper.selectByPrimaryKey(userId);
        if (null == user || StringUtils.isBlank(user.getGameChannel())) {
            return new BaseResponse(ErrorCode.user_invalid_session);
        }
        if (LangEnum.getLangByString(lang) == null) {
            return new BaseResponse(ErrorCode.parament_error);
        }
        user.setUserLang(lang);
        userMapper.updateByPrimaryKeySelective(user);
        return new BaseResponse();
    }

    public BaseResponse uploadOssAvaUrl(Long userId, String url) {
        User user = userMapper.selectByPrimaryKey(userId);
        if (null == user || StringUtils.isBlank(user.getGameChannel())) {
            return new BaseResponse(ErrorCode.user_invalid_session);
        }
        if (StringUtils.isBlank(url)) {
            return new BaseResponse(ErrorCode.parament_error);
        }
        user.setAvatar(url);
        userMapper.updateByPrimaryKeySelective(user);
        return new BaseResponse();
    }

    @Async
    public void upLocation(User user, String ipAddr) {
        String location = IPUtil.getLocationByIp(IPUtil.getIpAddr());
        if ((!"未知".equals(location) && (user.getCountry() == null || user.getCity() == null))) {
            String[] arry = location.split(" ");
            if (arry.length == 2 && !"未知".equals(location) && (user.getCountry() == null || user.getCity() == null)) {
                User upUser = new User();
                upUser.setCountry(arry[0]);
                upUser.setCity(arry[1]);
                userMapper.updateByPrimaryKeySelective(upUser);
            }
        }
    }
}
